from typing import TypedDict, Literal, Optional, Union
from langgraph.graph import StateGraph, START, END
from langgraph.types import interrupt
from langchain_core.messages import ToolMessage, HumanMessage, AIMessage

from 第7章Ai智能体系统的架构设计与模式应用.langgraph中可用的人机环路的交互 import HumanInterrupt

# 假设这些工具在其他地方定义
tools_by_name = {
    "hypothetical_tool": lambda **kwargs: f"工具执行结果: {kwargs}"
}

# 定义图状态，继承消息状态以用于对话历史记录
class AgentState(TypedDict):
    messages: list
    tool_calls: list

# 定义可能触发人工中断的图函数
def agent_node(state: AgentState):
    """智能体节点，决定是否调用工具或请求人工输入。"""
    messages = state["messages"]
    last_message = messages[-1] if messages else None

    # 假设智能体决定调用工具并具有工具调用详细信息
    tool_call_name = "hypothetical_tool"
    tool_call_args = {"input_arg": "accept"}

    # 构建 HumanInterrupt 对象
    request: HumanInterrupt = {
        "action_request": {
            "action": tool_call_name, # 操作名称是工具名称
            "args": tool_call_args  # 操作参数是工具参数
        },
        "config": {
            "allow_ignore": True, # 允许用户忽略工具调用
            "allow_respond": True, # 允许用户提供自由格式的响应
            "allow_edit": True,  # 允许用户编辑工具参数
            "allow_accept": True # 允许用户按原样接受工具调用
        },
        "description": f"智能体建议使用参数：`{tool_call_args}` 调用工具：`{tool_call_name}`。 你批准吗？", # Agent Inbox UI 的描述
    }

    # 调用 interrupt 函数，在列表中传递 HumanInterrupt 请求
    response_list = interrupt([request])
    response = response_list[0] if response_list else None # 从列表中提取第一个响应

    if response:
        if response['type'] == "accept":
            # 用户接受了工具调用，继续执行工具
            tool_result = tools_by_name[tool_call_name](**response['args']['args']) # 使用（可能已修改的）参数执行工具
            output_message = ToolMessage(content=str(tool_result), tool_call_id="example_id") # 使用结果创建 ToolMessage
        elif response['type'] == "edit":
            # 用户编辑了工具调用参数，使用编辑后的参数执行工具
            edited_args = response['args']['args'] # 从 ActionRequest 中提取编辑后的参数
            tool_result = tools_by_name[tool_call_name](**edited_args) # 使用编辑后的参数执行工具
            output_message = ToolMessage(content=str(tool_result), tool_call_id="example_id") # 使用结果创建 ToolMessage
        elif response['type'] == "response":
            # 用户提供了文本响应，据此处理
            user_response_text = response['args'] # 提取用户的文本响应
            output_message = AIMessage(content=f"用户响应：{user_response_text}。 根据响应继续进行。") # 创建 AIMessage 以确认响应
        elif response['type'] == "ignore":
            # 用户忽略了中断，据此处理
            output_message = AIMessage(content="人工中断被忽略。 继续进行，不进行工具调用。") # 创建 AIMessage，指示中断被忽略
        else:
            output_message = AIMessage(content="未知的人工响应类型。") # 处理意外的响应类型
    else:
        # 未收到响应（例如，中断处理超时或错误）
        output_message = AIMessage(content="未收到人工响应，继续进行，不进行干预。") # 处理未收到响应的情况

    return {"messages": [output_message]} # 返回更新的消息状态


# 构建 LangGraph 工作流
builder = StateGraph(AgentState)
builder.add_node("agent_step", agent_node)
builder.add_edge(START, "agent_step")
builder.add_edge("agent_step", END)

# 编译工作流
workflow = builder.compile()
workflow.invoke({"messages": ["讲一个关于猫的笑话"]})
